Module-level declarations

Types

Link copied to clipboard
struct _strategy

Represents a single strategy which can be used to register accounts. It is composed of three parts:

  • an operation, used to represent the usage of this strategy

  • a function that extracts account_details from the operation arguments

  • a function that performs any action required by the strategy, given the account and the operation arguments

The transaction that will actually perform the registration will be composed of:

  • optionally, evm_signers

  • the operation defined here

  • register_account

evm_signers must contain the signatures of all the EVM participants to the account that will be registered. If the account will be registered with two auth descriptors, all EVM signers of both auth descriptors must add their signatures there. The message to sign can be retrieved by get_register_account_message. FT signers must simply sign the whole transaction instead. If all signers are FT signers, evm_signers must be omitted.

The operation will contain some parameters which will be used by account_details and action. It should not run any code, except checking requirements to call the operation. One common requirement is that it is being used to register an account, and it can be checked with require_register_account_next_operation. Most other requirements should be checked in the action function. The mount name of the operation must be the name of the strategy in the map returned by strategy.

The register_account operation will take the name of the previous operation, find out the _strategy it represents, use the parameters in conjunction with _strategy.account_details to extract information about the account it needs to create, and call the _strategy.action function to run the code for the strategy.

Link copied to clipboard

Represents information about an account that will be created using a strategy.

Functions

Link copied to clipboard
function _no_action(account: account, strategy_params: gtv)

An empty function that can be used if a strategy does not need to perform checks for the account creation.

This should generally not be the function to use, but it can be useful for debugging and testing. Sometimes the _strategy.account_details function will be forced to have some requirements, and if those are considered enough this function could be passed in _strategy.action (by leaving action null in add_strategy, if used).

If your strategy will use no action, please double check that it does not have requirements that are so loose that they let users create infinite accounts, or your dapp may be vulnerable to DoS attacks.

Link copied to clipboard
function add_strategy(op: meta, account_details: (gtv) -> account_details, action: (account, gtv) -> unit?): map<text, _strategy>

Used to add new strategies to the dapp. This does not need to be called for FT4-defined strategies.

This function helps avoid a common issue where a strategy is registered with the wrong name. If that happens, many functions of this module will throw errors pointing to that strategy as missing, since they won't be able to find it.

Example usage:

operation my_strategy(
main: accounts.auth_descriptor,
disposable: accounts.auth_descriptor? = null
) {
strategies.require_register_account_next_operation();
}

function account_details(gtv) {
val params = struct<ras_open>.from_gtv(gtv);
val signers = accounts.get_signers(params.main);
return strategies.account_details(
account_id = accounts.get_account_id_from_signers(signers),
main = params.main,
disposable = params.disposable
);
}

function my_custom_logic(accounts.account, gtv) {
// custom logic that the strategy has to follow
}

@extend(strategies.strategy)
function () = strategies.add_strategy(
op = rell.meta(my_strategy),
account_details = account_details(*),
action = my_custom_logic(*)
);
Link copied to clipboard
@extendable function after_register_account(account: account)

Extendable function that allows the developer to add more functionality to the register_account function, after the registration happens.

This allows, for example, to add fees on registration or check that any given condition is present after the registration can be completed.

If this function throws an exception, the registration will not happen.

When using the transfer submodule, the strategies defined there already implement extensions of this function, requiring no additional code from the developer. This function should only be extended if functionality that is not found in the predefined strategies is required.

In some cases, creating a new strategy is a better alternative: this function will run on all account registrations, regardless of the strategy they used.

Throws if any extension of this function throws.

Link copied to clipboard

Builds a text description of an auth descriptor. It's used to represent the auth descriptor in the account registration message.

Link copied to clipboard

Builds a portion of the message that will be used to authorize account registration. This portion gives the information about the auth descriptors that will be added to the newly created account

In a standard usage of the library, this operation would have the mount name of ft4.register_account, found at external.accounts.registration.register_account

Link copied to clipboard

Builds a text description of a multi-sig auth descriptor. It's used to represent the auth descriptor in the account registration message.

Link copied to clipboard

Builds a portion of the message that will be used to authorize account registration. This portion gives the information about the operation that called register_account.

In a standard usage of the library, this operation would have the mount name of ft4.register_account, found at external.accounts.registration.register_account

Link copied to clipboard

Builds a text description of a single-sig auth descriptor. It's used to represent the auth descriptor in the account registration message.

Link copied to clipboard
@extendable function before_register_account(account_id: byte_array)

Extendable function that allows the developer to add more functionality to the register_account function, before the registration happens.

This allows, for example, to add fees on registration or check that any given condition is present before the registration can be completed.

If this function throws an exception, the registration will not happen.

When using the transfer submodule, the strategies defined there already implement extensions of this function, requiring no additional code from the developer. This function should only be extended if functionality that is not found in the predefined strategies is required.

In some cases, creating a new strategy is a better alternative: this function will run on all account registrations, regardless of the strategy they used.

Throws if any extension of this function throws.

Link copied to clipboard

Retrieves an account id given the strategy operation, using the account_details function defined for the _strategy in question.

Link copied to clipboard
function get_register_account_message(strategy_operation: gtx_operation, register_account_operation: gtx_operation): text

Gives a default message used by EVM wallets to authorize the account registration.

Throws if the strategy cannot be found. If strategy_name is correct, this could also be caused by having misconfigured the registration defined in the function that extends strategy in such a way that the strategy name and the _strategy.op.mount_name are not the same value.

Link copied to clipboard
function get_strategy(strategy_name: text): _strategy

Returns a strategy, given the mount name of the operation that defines it.

Throws "MISSING STRATEGY" if the strategy cannot be found. If strategy_name is correct, this could also be caused by having misconfigured the registration defined in the function that extends strategy in such a way that the strategy name and the _strategy.op.mount_name are not the same value.

Link copied to clipboard

Checks whether an operation is a strategy operation that can be used on this chain. Strategy operations not registered through extensions of strategy will return false, as they won't be usable on this chain.

Link copied to clipboard

Registers an account on this chain, using a certain strategy.

Can only be called from an operation.

It will register the account with the account_details retrieved by _strategy.account_details, and using the logic found in _strategy.action.

The new account will have a main auth descriptor given by account_details.main, and optionally a disposable auth descriptor given by account_details.disposable

It expects all signers of both auth descriptors to have signed this transaction.

Throws if the operation that came just before this one cannot be handled. Common cases are:

  • the operation is not registered as a strategy operation through extensions of strategy

  • the operation has been misconfigured, and its name does not match the operation mount name

Throws if the signature verification is unsuccessful. Common cases are:

  • evm_signatures is misconfigured:

    • any of the signers and signatures don't match in the exact order they're found

    • any of the signatures is null

    • there's more signatures than signers

  • a signature from one of the auth descriptor participants is missing:

    • an EVM signer is specified but the signature is not found in evm_signatures

    • an FT signer is specified but the signature is not in the transaction

    • a signer passed is neither an EVM nor an FT signer (its length does not match either of core.auth.EVM_ADDRESS_SIZE and core.auth.FT_PUBKEY_SIZE)

Throws if either auth descriptor is invalid. Common cases include:

  • the main auth descriptor has expiration rules instead of core.accounts.GTV_NULL

  • the disposable auth descriptor's expiration rules:

    • is a complex rule with too many rule components

    • has already expired

    • is not the valid GTV representation of a rule

  • errors with the args field:

    • some required flags are missing

    • in multi-sig auth descriptors, the required_signatures field:

      • is 0 or less

      • is greater than the number of signers

Throws if core.accounts.AUTH_DESCRIPTORS_PER_ACCOUNT_UPPER_BOUND is set to 1 and account_details.disposable is not null.

Throws if some conditions added in development through extensions (before_register_account or after_register_account) aren't met

Link copied to clipboard

Verifies that the next operation in the transaction is an operation that can be used to register accounts. Any operation that is whitelisted to be called after evm_signatures is considered valid here.

Throws "MISSING REGISTER ACCOUNT" if:

  • the next operation is not whitelisted

  • this is the last operation in the transaction

Throws if the chromia.yml cannot be parsed for evm_signatures_authorized_operations, e.g. if some elements are not text or there are duplicates.

Link copied to clipboard
@extendable function strategy(): map<text, _strategy>

Returns a map of all possible strategies used to register accounts on this chain. Can be extended to add custom strategies and make them work seamlessly with the existing register_account framework.

The map pairs up a strategy operation mount name and the _strategy struct representing it. The name must be the mount name of _strategy.op

To avoid misconfiguring strategies, it is strongly recommended to add extensions to this function using add_strategy.

Throws if any extension of this function throws.